#include<iostream>
#include<string>
#include"def.h"
#define ll unsigned long long
using namespace std;
char* buf;
unsigned int A, B, C, D;
unsigned int ori_res[4];
unsigned int xue_res[4];
string char2HEX(const unsigned char h[]) {
	string res = "";
	char list[] = "0123456789ABCDEF";
	for (int i = 0; i < 16; i += 4) {
		res += list[h[i] >> 4];		res += list[h[i] & 0xF];
		res += list[h[i + 1] >> 4];	res += list[h[i + 1] & 0xF];
		res += list[h[i + 2] >> 4];	res += list[h[i + 2] & 0xF];
		res += list[h[i + 3] >> 4];	res += list[h[i + 3] & 0xF];
		res += " ";
	}
	return res;
}
void MD5(string s) {
	cout << "s:" << s << endl;
	int len = s.length() << 3;//数据长度
	int groupNum = ((s.length() + 8) >> 6) + 1;//64字节的个数
	int fillNum = groupNum * 64 - s.length();//总需要填充的字节数(800000和数据长度)
	int firstPos = (s.length());
	for (int i = 0; i < fillNum; i++) {
		s += (unsigned char)0;
	}
	s[firstPos] = (unsigned char)0x80;
	memcpy(&s[(groupNum << 6) - 8], &len, 4);

	A = 0x67452301;
	B = 0xefcdab89;
	C = 0x98badcfe;
	D = 0x10325476;
	//分组循环
	unsigned int a, b, c, d;
	for (int i = 0; i < groupNum; i++) {//每一组都这样做
		a = A, b = B, c = C, d = D;
		for (int j = 0; j < 64; j++) {
			unsigned int f, m, temp;
			if (j < 16) {
				f = F(b, c, d);
				memcpy(&m, &s[((i) * 64) + (j << 2)], 4);
			}
			else if (j < 32)
			{
				f = G(b, c, d);
				memcpy(&m, &s[(i) * 64 + (((5 * j + 1) & 0xF) << 2)], 4);
			}
			else if (j < 48)
			{
				f = H(b, c, d);
				memcpy(&m, &s[(i) * 64 + (((3 * j + 5) & 0xF) << 2)], 4);
			}
			else {
				f = I(b, c, d);
				memcpy(&m, &s[(i) * 64 + (((7 * j) & 0xF) << 2)], 4);
			}
			//printf("\n第%d次循环：\na:%x, b:%x, c:%x, d:%x, F:%x, K:%x, M:%x, s:%x\n", j, a, b, c, d, f, K[j], m, S[j]);
			temp = b;
			b = b + shift(a + f + m + K[j], S[j]);
			a = d;
			d = c;
			c = temp;
		}
		A = (a + A);
		B = (b + B);
		C = (c + C);
		D = (d + D);
	}
	A = Small(A);
	B = Small(B);
	C = Small(C);
	D = Small(D);

	printf("MD5值为:%8X %8X %8X %8X\n", A, B, C, D);
}
int main() {
	string s = "12345678901234567890123456789012345678901234567890123456789012345678901234567890";
	MD5(s);
	memcpy(ori_res, &A, 4); memcpy(&ori_res[1], &B, 4); memcpy(&ori_res[2], &C, 4); memcpy(&ori_res[3], &D, 4);
	char sym[] = "!@#$%^& ";
	for (int i = 0; i < 8; i++) {
		MD5(s + sym[i]);
		memcpy(xue_res, &A, 4); memcpy(&xue_res[1], &B, 4); memcpy(&xue_res[2], &C, 4); memcpy(&xue_res[3], &D, 4);
		int count = 0;
		for (int i = 0; i < 4; i++) {
			unsigned int temp = ori_res[i] ^ xue_res[i];
			while (temp) {
				if (temp & 1)count++;
				temp = temp >> 1;
			}
		}
		printf("字符串后接%c的MD5改变的位数为%d\n\n", sym[i], count);
	}
}